const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

/**
 * 上传工具类
 */
class UploadUtil {
  constructor(app) {
    this.app = app;
    this.config = app.config.upload;
  }

  /**
   * 生成上传文件的保存路径
   * @param {string} filename 原始文件名
   * @return {object} 包含路径信息的对象
   */
  generateFilePath(filename) {
    // 获取文件扩展名
    const ext = path.extname(filename);
    // 生成随机文件名
    const randomName = crypto.randomBytes(16).toString('hex') + ext;

    let savePath = this.config.basePath;
    let yearMonthDir = '';

    // 如果启用日期目录
    if (this.config.enableDateDir) {
      yearMonthDir = this.generateYearMonthDir();
      savePath = path.join(savePath, yearMonthDir);

      // 确保目录存在
      const fullDirPath = path.join(this.app.baseDir, savePath);
      if (!fs.existsSync(fullDirPath)) {
        fs.mkdirSync(fullDirPath, { recursive: true });
      }
    }

    // 完整文件路径
    const filePath = path.join(savePath, randomName);
    const fullFilePath = path.join(this.app.baseDir, filePath);

    return {
      filePath, // 相对路径
      fullFilePath, // 绝对路径
      randomName, // 随机文件名
      savePath, // 保存目录
      yearMonthDir, // 年月目录（用于URL生成）
    };
  }

  /**
   * 生成年月目录
   * @return {string} 年月目录路径
   */
  generateYearMonthDir() {
    const date = new Date();
    const year = date.getFullYear().toString();
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    return path.join(year, month);
  }

  /**
   * 生成图片URL路径
   * @param {string} randomName 随机文件名
   * @return {string} URL路径
   */
  generateImageUrlPath(randomName) {
    if (this.config.enableDateDir) {
      const date = new Date();
      const year = date.getFullYear().toString();
      const month = (date.getMonth() + 1).toString().padStart(2, '0');
      // URL路径必须使用正斜杠，不能使用path.join（在Windows上会生成反斜杠）
      const yearMonthDir = `${year}/${month}`;
      return `${yearMonthDir}/${randomName}`;
    } else {
      return randomName;
    }
  }

  /**
   * 保存上传的文件
   * @param {Stream} fileStream 文件流
   * @param {string} fullFilePath 完整文件路径
   * @return {Promise}
   */
  async saveFile(fileStream, fullFilePath) {
    return new Promise((resolve, reject) => {
      const writeStream = fs.createWriteStream(fullFilePath);

      fileStream.pipe(writeStream);

      writeStream.on('finish', () => {
        resolve(true);
      });

      writeStream.on('error', error => {
        // 如果写入失败，删除文件
        if (fs.existsSync(fullFilePath)) {
          fs.unlinkSync(fullFilePath);
        }
        reject(error);
      });
    });
  }

  /**
   * 删除文件
   * @param {string} fullFilePath 完整文件路径
   * @return {boolean}
   */
  deleteFile(fullFilePath) {
    if (fs.existsSync(fullFilePath)) {
      fs.unlinkSync(fullFilePath);
      return true;
    }
    return false;
  }
}

module.exports = UploadUtil;
